Skip to content

Remove ResolveXHandle indirections#45292

Merged
jkotas merged 8 commits into
dotnet:masterfrom
benaadams:ResolveType
Dec 2, 2020
Merged

Remove ResolveXHandle indirections#45292
jkotas merged 8 commits into
dotnet:masterfrom
benaadams:ResolveType

Conversation

@benaadams

Copy link
Copy Markdown
Member

@benaadams

Copy link
Copy Markdown
Member Author

Current method

; Assembly listing for method ModuleHandle:ResolveTypeHandleInternal(RuntimeModule,int,ref,ref):RuntimeType
; Lcl frame size = 248

; Total bytes of code 602, prolog size 55, PerfScore 179.03, instruction count 158 (MethodHash=dc0f0d48) for method ModuleHandle:ResolveTypeHandleInternal(RuntimeModule,int,ref,ref):RuntimeType
; ============================================================

New method

; Assembly listing for method ModuleHandle:ResolveTypeHandleInternal(RuntimeModule,int):RuntimeType
; Lcl frame size = 216

; Total bytes of code 368, prolog size 48, PerfScore 110.13, instruction count 101 (MethodHash=240fc648) for method ModuleHandle:ResolveTypeHandleInternal(RuntimeModule,int):RuntimeType
; ============================================================

@GrabYourPitchforks

Copy link
Copy Markdown
Member

The existing code path contains calls to helpers which no-op if given null inputs.

What is the benefit of this change? Does it measurably increase perf for some scenario?

@jkotas jkotas added the tenet-performance Performance related issue label Nov 28, 2020
@jkotas

jkotas commented Nov 28, 2020

Copy link
Copy Markdown
Member

Could you please share numbers for what this is improving?

@benaadams

benaadams commented Nov 28, 2020

Copy link
Copy Markdown
Member Author

Just looking into where time is going for FilterCustomAttributeRecord for #45121 and noticed there is a bunch of unneeded work 2 x CopyRuntimeTypeHandles 2 x ChkCastAny, 2 x ConvertToTypeHandleArray; extra 32 bytes of stack cleared etc

However FilterCustomAttributeRecord never calls it with any generic arguments so all this can be skipped

image

Details
-; Lcl frame size = 248
+; Lcl frame size = 216
 
G_..._IG01:
        push     rbp
        push     r15
        push     r14
...
        push     rdi
        push     rsi
        push     rbx
-       sub      rsp, 248
-       lea      rbp, [rsp+130H]
+       sub      rsp, 216
+       lea      rbp, [rsp+110H]
        xorps    xmm4, xmm4
-       movaps   xmmword ptr [rbp-90H], xmm4
-       movaps   xmmword ptr [rbp-80H], xmm4
        movaps   xmmword ptr [rbp-70H], xmm4
        movaps   xmmword ptr [rbp-60H], xmm4
+       movaps   xmmword ptr [rbp-50H], xmm4
        xor      rax, rax
-       mov      qword ptr [rbp-50H], rax
+       mov      qword ptr [rbp-40H], rax
        mov      gword ptr [rbp+10H], rcx
-       mov      ebx, edx
-       mov      rsi, r8
-       mov      rdi, r9

+       mov      esi, edx
        mov      rcx, gword ptr [rbp+10H]
        call     [ModuleHandle:ValidateModulePointer(RuntimeModule)]
-       lea      rcx, bword ptr [rbp-58H]
+       lea      rcx, bword ptr [rbp-50H]
        mov      rdx, gword ptr [rbp+10H]
        call     [ModuleHandle:GetMetadataImport(RuntimeModule):MetadataImport]
-       mov      rcx, qword ptr [rbp-50H]
-       mov      edx, ebx
+       mov      rcx, qword ptr [rbp-48H]
+       mov      edx, esi
        call     [MetadataImport:_IsValidToken(long,int):bool]
        test     al, al
-       je       G_M62135_IG21
+       je       G_M14775_IG07

-       test     rsi, rsi
-       jne      SHORT G_M62135_IG05

        xor      rcx, rcx
-       jmp      SHORT G_M62135_IG06

-       mov      rcx, rsi
-       call     [Object:MemberwiseClone():Object:this]
-       mov      rcx, rax

-       call     [CORINFO_HELP_READYTORUN_CHKCAST]
-       mov      rsi, rax
-       test     rdi, rdi
-       jne      SHORT G_M62135_IG08

-       xor      rcx, rcx
-       jmp      SHORT G_M62135_IG09

-       mov      rcx, rdi
-       call     [Object:MemberwiseClone():Object:this]
-       mov      rcx, rax

-       call     [CORINFO_HELP_READYTORUN_CHKCAST]
-       mov      rdi, rax
-       lea      rdx, [rbp-40H]
-       mov      gword ptr [rbp+20H], rsi
-       mov      rcx, rsi
-       call     [RuntimeTypeHandle:CopyRuntimeTypeHandles(ref,byref):ref]
-       mov      r14, rax
-       lea      rdx, [rbp-48H]
-       mov      gword ptr [rbp+28H], rdi
-       mov      rcx, rdi
-       call     [RuntimeTypeHandle:CopyRuntimeTypeHandles(ref,byref):ref]
-       mov      gword ptr [rbp-60H], r14
-       test     r14, r14
-       je       SHORT G_M62135_IG11

-       mov      rcx, gword ptr [rbp-60H]
-       cmp      dword ptr [rcx+8], 0
-       jne      SHORT G_M62135_IG12

-       xor      r8, r8
-       jmp      SHORT G_M62135_IG13

-       mov      r8, gword ptr [rbp-60H]
-       cmp      dword ptr [r8+8], 0
-       jbe      G_M62135_IG22
-       mov      r8, gword ptr [rbp-60H]
-       add      r8, 16

-       mov      gword ptr [rbp-68H], rax
-       test     rax, rax
-       je       SHORT G_M62135_IG15

-       mov      rcx, gword ptr [rbp-68H]
-       cmp      dword ptr [rcx+8], 0
-       jne      SHORT G_M62135_IG16

+       mov      gword ptr [rbp-40H], rcx
+       lea      rcx, [rbp+10H]
+       mov      rdx, gword ptr [rbp+10H]
+       mov      rdx, qword ptr [rdx+32]
+       lea      r8, [rbp-40H]
+       lea      r9, bword ptr [rbp-60H]
+       mov      qword ptr [r9], rcx
+       mov      qword ptr [r9+8], rdx
        xor      rcx, rcx
-       jmp      SHORT G_M62135_IG17

-       mov      rcx, gword ptr [rbp-68H]
-       cmp      dword ptr [rcx+8], 0
-       jbe      G_M62135_IG22
-       mov      rcx, gword ptr [rbp-68H]
-       add      rcx, 16

-       xor      rdx, rdx
-       mov      gword ptr [rbp-70H], rdx
-       lea      rdx, [rbp+10H]
-       mov      r9, gword ptr [rbp+10H]
-       mov      r9, qword ptr [r9+32]
-       mov      eax, dword ptr [rbp-40H]
-       mov      r10d, dword ptr [rbp-48H]
-       lea      r11, [rbp-70H]
-       lea      r14, bword ptr [rbp-80H]
-       mov      qword ptr [r14], rdx
-       mov      qword ptr [r14+8], r9
        mov      qword ptr [rsp+20H], rcx
-       mov      dword ptr [rsp+28H], r10d
-       mov      qword ptr [rsp+30H], r11
-       lea      rcx, bword ptr [rbp-80H]
-       mov      bword ptr [rbp-90H], rcx
-       mov      edx, ebx
-       mov      dword ptr [rbp-84H], edx
-       mov      qword ptr [rbp-98H], r8
-       mov      r9d, eax
-       mov      dword ptr [rbp-88H], r9d
-       lea      rcx, [rbp-F0H]

+       mov      dword ptr [rsp+28H], ecx
+       mov      qword ptr [rsp+30H], r8
+       lea      rcx, bword ptr [rbp-60H]
+       mov      bword ptr [rbp-70H], rcx
+       mov      edx, esi
+       mov      dword ptr [rbp-64H], edx
+       xor      r8, r8
+       mov      qword ptr [rbp-78H], r8
+       xor      r9d, r9d
+       mov      dword ptr [rbp-68H], r9d
+       lea      rcx, [rbp-D0H]

        call     [CORINFO_HELP_JIT_PINVOKE_BEGIN]
        mov      rax, qword ptr [(reloc)]
-       mov      rcx, bword ptr [rbp-90H]
-       mov      edx, dword ptr [rbp-84H]
-       mov      r8, qword ptr [rbp-98H]
-       mov      r9d, dword ptr [rbp-88H]
+       mov      rcx, bword ptr [rbp-70H]
+       mov      edx, dword ptr [rbp-64H]
+       mov      r8, qword ptr [rbp-78H]
+       mov      r9d, dword ptr [rbp-68H]

        call     qword ptr [rax]ModuleHandle:ResolveType(QCallModule,int,long,int,long,int,ObjectHandleOnStack)
-       lea      rcx, [rbp-F0H]
+       lea      rcx, [rbp-D0H]
        call     [CORINFO_HELP_JIT_PINVOKE_END]
-       mov      rax, gword ptr [rbp-70H]
+       mov      rax, gword ptr [rbp-40H]

        lea      rsp, [rbp-38H]
        pop      rbx
        pop      rsi

@benaadams

Copy link
Copy Markdown
Member Author

CopyRuntimeTypeHandles, ChkCastAny and ConvertToTypeHandleArray all have early outs but they also don't inline so its 10 additional method calls per call to FilterCustomAttributeRecord

Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs Outdated
@jkotas

jkotas commented Nov 28, 2020

Copy link
Copy Markdown
Member

CopyRuntimeTypeHandles, ChkCastAny and ConvertToTypeHandleArray all have early outs but they also don't inline so its 10

Would it better to just add a check around these calls instead of duplicating the implementation?

IntPtr[] typeInstantiationContextHandles = null
int typeInstCount = 0;

if (typeInstantiationContext != null)
{
    typeInstantiationContext = (RuntimeTypeHandle[])typeInstantiationContext.Clone();
    typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out int typeInstCount);
}

Note that this check is sort of there already thanks to ?. operator.

@benaadams

Copy link
Copy Markdown
Member Author

Would it better to just add a check around these calls instead of duplicating the implementation?

Have done this; but it pushes up the register pressure the stack usage for the common non-generic case? Probably not much in the scheme of things

@benaadams

Copy link
Copy Markdown
Member Author

Could do the unification with ResolveMethodHandle also if you prefer moving for less methods?

@jkotas

jkotas commented Nov 28, 2020

Copy link
Copy Markdown
Member

Yes, it would be nice for consistency

@benaadams benaadams changed the title Skip fixed and GC.KeepAlive for ResolveTypeHandleInternal when no generics Remove ResolveXHandle indirections Nov 28, 2020
@GrabYourPitchforks

Copy link
Copy Markdown
Member

I opened #45302 to track eliding the cast resulting from:

RuntimeTypeHandle[]? handles = (RuntimeTypeHandle[]?)originalHandles?.Clone();

@benaadams

Copy link
Copy Markdown
Member Author

Yes, it would be nice for consistency

Did ResolveType, ResolveMethod, ResolveField

Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
Comment thread src/coreclr/src/vm/runtimehandles.cpp Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs Outdated
@benaadams

Copy link
Copy Markdown
Member Author

windows x86 Release error is #45317

@benaadams

Copy link
Copy Markdown
Member Author

😅 My Linq is bad for the tests

System.InvalidOperationException : The test method expected 1 parameter value, but 27 parameter values were provided.

@benaadams

Copy link
Copy Markdown
Member Author

Rebased

@benaadams

Copy link
Copy Markdown
Member Author

Seems happy with the crossgen revert

@jkotas jkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM otherwise

Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
@jkotas

jkotas commented Nov 30, 2020

Copy link
Copy Markdown
Member

@GrabYourPitchforks @steveharter Could you please take a look as well as reflection area owners?

@benaadams

Copy link
Copy Markdown
Member Author

Feed timeouts on same variants; rebased to trigger CI

@benaadams

Copy link
Copy Markdown
Member Author

Rebased for CI

@GrabYourPitchforks GrabYourPitchforks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
Comment thread src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs Outdated
@GrabYourPitchforks

Copy link
Copy Markdown
Member

The two comments I left were nits. Feel free to address them or leave them as-is at your discretion. I personally don't like target new, but there's seemingly no prohibition against it, so whatever. :)

@benaadams

Copy link
Copy Markdown
Member Author

I personally don't like target new, but there's seemingly no prohibition against it, so whatever. :)

Could always go var instead... 😉

  1. We only use var when it's obvious what the variable type is (e.g. var stream = new FileStream(...) not var stream = OpenStandardInput()).

@jkotas

jkotas commented Dec 2, 2020

Copy link
Copy Markdown
Member

Thank you!

@benaadams benaadams deleted the ResolveType branch December 2, 2020 17:27
@ghost ghost locked as resolved and limited conversation to collaborators Jan 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants